package avicit.rme.back.apigenerator.rest;

import com.avic.szzx.service.MysqlService;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import avicit.rme.back.apigenerator.dto.ApiDataQueryConfig;
import avicit.rme.back.apigenerator.dto.ApiDefinition;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api-generator")
public class ApiGeneratorController {

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private RequestMappingHandlerMapping requestMappingHandlerMapping;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private HttpServletRequest currentRequest;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private MysqlService mysqlService;

    private final Map<String, ApiDefinition> registeredApis = new HashMap<>();
    private final Map<String, ApiDataQueryConfig> apiDataConfigs = new HashMap<>();

    // API创建端点
    @PostMapping("/create-get-api")
    public Map<String, Object> createGetApi(@RequestBody ApiDefinition definition) {
        return registerApi(definition, RequestMethod.GET);
    }

    @PostMapping("/create-post-api")
    public Map<String, Object> createPostApi(@RequestBody ApiDefinition definition) {
        return registerApi(definition, RequestMethod.POST);
    }

    @PostMapping("/create-data-api")
    public Map<String, Object> createDataApi(@RequestBody ApiDataQueryConfig config) {
        ApiDefinition definition = new ApiDefinition();
        definition.setPath(config.getApiPath());
        definition.setRequestParams(config.getRequestParams());
        definition.setParamTypes(Collections.nCopies(config.getRequestParams().size(), "String"));
        definition.setReturnType("List");

        Map<String, Object> result = registerApi(definition, RequestMethod.GET);
        apiDataConfigs.put(config.getApiPath(), config);

        result.put("dataConfig", config);
        return result;
    }

    @PostMapping("/create-data-api2")
    public Map<String, Object> createDataApi2(@RequestBody ApiDataQueryConfig config) {
        ApiDefinition definition = new ApiDefinition();
        definition.setPath(config.getApiPath());
        definition.setRequestParams(config.getRequestParams());
        definition.setParamTypes(Collections.nCopies(config.getRequestParams().size(), "String"));
        definition.setReturnType("List");

        Map<String, Object> result = registerApi(definition, RequestMethod.GET);
        apiDataConfigs.put(config.getApiPath(), config);

        result.put("dataConfig", config);
        return result;
    }

    // 动态API处理器
    @RequestMapping
    public Object dynamicApiHandler(@RequestParam Map<String, String> allParams) {
        String path = currentRequest.getRequestURI();
        ApiDefinition definition = registeredApis.get(path);

        if (definition == null) {
            return createErrorResponse("API not found: " + path);
        }

        // 验证必需参数
        List<String> missingParams = definition.getRequestParams().stream()
                .filter(param -> !allParams.containsKey(param))
                .collect(Collectors.toList());

        if (!missingParams.isEmpty()) {
            return createErrorResponse("Missing required parameters: " + missingParams);
        }

        // 处理数据查询API
        if (apiDataConfigs.containsKey(path)) {
            return handleDataQuery(path, allParams);
        }

        // 默认处理
        return createSuccessResponse(definition.toString(), allParams);
    }

    // 辅助方法
    private Map<String, Object> registerApi(ApiDefinition definition, RequestMethod method) {
        Map<String, Object> response = new HashMap<>();

        try {
            if (registeredApis.containsKey(definition.getPath())) {
                throw new IllegalArgumentException("API path already exists: " + definition.getPath());
            }

            RequestMappingInfo.Builder builder = RequestMappingInfo
                    .paths(definition.getPath())
                    .methods(method);

            if (definition.getRequestParams() != null && !definition.getRequestParams().isEmpty()) {
                builder.params(definition.getRequestParams().toArray(new String[0]));
            }

            RequestMappingInfo requestMappingInfo = builder.build();
            Method targetMethod = ApiGeneratorController.class.getDeclaredMethod(
                    "dynamicApiHandler", Map.class);

            requestMappingHandlerMapping.registerMapping(
                    requestMappingInfo, this, targetMethod);

            registeredApis.put(definition.getPath(), definition);

            response.put("status", "success");
            response.put("message", "API created successfully");
            response.put("apiDefinition", definition);

        } catch (Exception e) {
            response.put("status", "error");
            response.put("message", e.getMessage());
        }

        return response;
    }

    private Object handleDataQuery(String path, Map<String, String> params) {
        ApiDataQueryConfig config = apiDataConfigs.get(path);

        try {
            // 按参数顺序获取值
            Object[] paramValues = config.getRequestParams().stream()
                    .map(params::get)
                    .toArray();

//            String sql = buildQuerySql(config, paramValues);
            String sql = "select id,username from user_info";
            List<Map<String, Object>> result = jdbcTemplate.queryForList(sql);

            return createSuccessResponse("data", result);

        } catch (Exception e) {
            return createErrorResponse("Query failed: " + e.getMessage());
        }
    }

    private String buildQuerySql(ApiDataQueryConfig config, Object... params) {
        StringBuilder sql = new StringBuilder("SELECT ");

        sql.append(config.getFields() == null || config.getFields().isEmpty() ?
                "*" : String.join(", ", config.getFields()));

        sql.append(" FROM ").append(config.getTableName());

        if (config.getConditions() != null && !config.getConditions().isEmpty()) {
            sql.append(" WHERE ");

            List<String> conditions = new ArrayList<>();
            for (int i = 0; i < config.getConditions().size(); i++) {
                String condition = config.getConditions().get(i)
                        .replace("?", "'" + params[i] + "'");
                conditions.add(condition);
            }

            sql.append(String.join(" AND ", conditions));
        }

        if (config.getOrderBy() != null && !config.getOrderBy().isEmpty()) {
            sql.append(" ORDER BY ").append(config.getOrderBy());
        }

        if (config.getPageSize() > 0) {
            int page = params.length > config.getConditions().size() ?
                    Integer.parseInt(params[params.length - 1].toString()) : 1;
            int offset = (page - 1) * config.getPageSize();
            sql.append(" LIMIT ").append(offset).append(", ").append(config.getPageSize());
        }

        return sql.toString();
    }

    private Map<String, Object> createSuccessResponse(Object data) {
        Map<String, Object> response = new HashMap<>();
        response.put("status", "success");
        response.put("data", data);
        response.put("timestamp", new Date());
        return response;
    }

    private Map<String, Object> createSuccessResponse(String key, Object value) {
        Map<String, Object> response = new HashMap<>();
        response.put("status", "success");
        response.put(key, value);
        response.put("timestamp", new Date());
        return response;
    }

    private Map<String, Object> createErrorResponse(String message) {
        Map<String, Object> response = new HashMap<>();
        response.put("status", "error");
        response.put("message", message);
        response.put("timestamp", new Date());
        return response;
    }
}